﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Windows.Threading;
using System.Windows;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace Moop.UI.Common.ViewModels
{
    public abstract class BaseViewModel : INotifyPropertyChanged, IDisposable
    {
        public event PropertyChangedEventHandler PropertyChanged;


        protected BaseViewModel()
        {
        }
        
        private bool m_IsBusy;
        public bool IsBusy
        {
            get { return m_IsBusy; }
            set
            {
                m_IsBusy = value;    
                OnPropertyChanged("IsBusy");
            }
        }

        protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpresion)
        {
            var property = (MemberExpression)propertyExpresion.Body;
            VerifyPropertyExpression<T>(propertyExpresion, property);
            this.OnPropertyChanged(property.Member.Name);
        }


        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        protected void SetValue<T>(ref T refValue, T newValue, Expression<Func<T>> propertyExpresion)
        {
            if (!object.Equals(refValue, newValue))
            {
                refValue = newValue;
                this.OnPropertyChanged(propertyExpresion);
            }
        }


        protected void SetValue<T>(ref T refValue, T newValue, Action valueChanged)
        {
            if (!object.Equals(refValue, newValue))
            {
                refValue = newValue;
                valueChanged();
            }
        }


        [Conditional("DEBUG")]
        private void VerifyPropertyExpression<T>(Expression<Func<T>> propertyExpresion, MemberExpression property)
        {
            if (property.Member.GetType().IsAssignableFrom(typeof(PropertyInfo)))
            {
                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    "Invalid Property Expression {0}",
                    propertyExpresion));
            }

            var instance = property.Expression as ConstantExpression;
            if (instance.Value != this)
            {
                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    "Invalid Property Expression {0}",
                    propertyExpresion));
            }
        }


        public void Dispose()
        {
            OnDispose();
        }


        protected virtual void OnDispose()
        {
        }


    }
 }
